iT邦幫忙

2026 iThome 鐵人賽

DAY 29
1
ChatGPT & Codex

利用Custom GPT+遊戲感來寫PRD系列 第 29

【Day 29】Mermaid 轉圖進 Word:流程圖變成一坨

  • 分享至 

  • xImage
  •  

昨天把 PRD 該有的東西都湊齊了:摘要、角色、流程、資料、例外、工時。聊到最後使用者通常只想做一件事:把它下載成一份 Word 拿去開會。聽起來是最簡單的收尾,實際做起來卡了不少時間。

問題出在那張流程圖。

前面整套設計,流程圖都是用 Mermaid 寫的純文字。在對話畫面裡,GPTs 有原生的 Mermaid 顯示器,那段程式碼會即時渲染成漂亮的方塊跟箭頭,使用者看得很開心。可是一旦生成 Word,Word 不認得 Mermaid。它只會把那段 flowchart TD 原樣當成文字塞進去,使用者打開檔案,看到的是這樣一段內容:

flowchart TD
    A["UI-01 登入頁"] --> B{是否符合資格}
    B -->|符合| C["UI-02 服務列表頁"]
    B -->|不符合| D["UI-03 資格不符提示"]

當初會用 Mermaid,是看上它是純文字:後續這份文件要交給 AI 接手開發時,機器解析比圖片容易得多。但這個優勢只在機器那一端成立。整份文件最關鍵的一段,在 Word 裡變成一段沒有人會逐行去讀的原始碼。

1788791872185


第一個直覺:在對話裡就先轉成圖

我一開始想得很單純:那就別等到 Word,從頭到尾都用圖不就好了?使用者每改一次流程,我就在背後把 Mermaid 轉成 JPG 顯示。

GPT 要轉圖只能靠 Code Interpreter,那是一個沙箱裡的 Python 環境。實際呼叫才發現它沒有 mermaid-cli、沒有 Node、也沒有對外網路可以連 mermaid.live。Mermaid 的官方渲染本來就是跑在瀏覽器或 Node 上的,純 Python 沙箱裡沒有現成的渲染器,第一次跑就直接報錯。

退一步說,就算轉得出來,每改一版流程就轉一次圖,每次轉檔好幾秒,對話節奏會被拖垮。使用者還在跟我來回調流程的箭頭,畫面卻一直在轉圈圈,這體驗很糟。

所以這條路兩邊都不通:技術上沙箱轉不動,體驗上也不該轉。

改方法:預覽用渲染,Word 才轉檔

坑踩到這裡,設計反而清楚了。把「看」跟「交付」拆成兩件事。

預覽階段

做法:直接吐 mermaid 程式碼區塊,靠 GPTs 原生顯示器即時渲染。

不轉圖。使用者調流程調得多勤都無所謂,渲染是顯示器即時做的,零成本。這個階段的目標是「快速看、快速改」,圖糊一點、醜一點都沒關係,能即時反映改動最重要。

Word 交付階段

做法:使用者明確說「產生 Word」,才動用 Code Interpreter 把 Mermaid 轉成 JPG,再用 python-docx 把圖嵌進文件。

整個轉檔的重活,延到最後一刻、而且只做一次。這也是為什麼鼠勾以的交付是兩段式的:先給你可以直接複製的 Markdown 全文,Word 檔當成可選的打包,你要才生成。沒人要 Word 的話,根本不用碰 Code Interpreter。

把這兩段攤開來看,分界很乾淨:對話階段優先「即時」,犧牲畫質;交付階段優先「能看」,才付轉檔的代價。同一張流程圖,在兩個階段用兩種方式呈現。

後來多問一句:這份要拿去討論,還是要定稿

上面這套用了一陣子,還是不夠。

需求方PM 要這份文件通常有兩個時機。一個是要帶去跟 SA、IT 開會,那份得排版、能印、圖要看得到。另一個是自己收工存檔,或是貼到內部知識庫、丟給下一棒的工具接手,那種要的是乾淨的純文字。我早期一律給 Word,第二種人拿到手還得自己反白複製、再把格式清一遍。

所以在產下載檔之前,多問一句:

這份要拿去跟 IT/SA 討論,還是先定稿?

選「討論」才生成 Word。選「定稿」就直接把對話裡那份 Markdown 全文當正本,不碰 Code Interpreter。

這裡踩到一個當下沒料到的問題。我測「我要 Markdown」的時候,它確實給了我一個檔案,副檔名也是 .md,但打開一看,內容是走完 Word 轉檔流程、結構已經被重排過的版本。它把「給我 Markdown」理解成「把 Word 那條路走完,最後換個副檔名」。另一次我說「定稿了」,它回我一個改了檔名的 Word。

現在寫死了:Markdown 正本就是對話裡組好的那段純文字,不生成檔案、不呼叫 Code Interpreter、不經過 Word。使用者說要 Markdown 或純文字,一律指回對話內全文。

python-docx 把圖塞進對的位置

真的要生 Word 的時候,流程大概是這樣串起來:

from docx import Document
from docx.shared import Cm

doc = Document()
# ...前面各章節照模板填...

# 3.0 端對端流程圖:把轉好的 JPG 嵌進來
doc.add_heading('3.0 端對端流程圖', level=2)
doc.add_picture('flowchart.jpg', width=Cm(15))

ps:這段 code 其實是 GPT 自己生的,我沒手刻。我做的只有把需求講清楚(圖嵌在 3.0、寬度 15 公分、轉失敗要有 fallback),剩下交給它寫。這剛好就是整個工具想傳達的事:人把需求說明白,產出讓工具去生。

寬度我固定抓 15 公分,剛好是 A4 直式扣掉邊界後一張圖塞得下、又不會小到看不清節點文字的尺寸。這個數字也是試出來的,太寬會擠破版面,太窄則 UI 編號全糊在一起。

轉圖的時候有一個必須固定的設定:強制 curve: linear。Mermaid 預設把箭頭畫成曲線,簡單的圖還好,節點一多就會互相交疊、看不出哪條連到哪裡。在 init 裡指定直線連接,圖才讀得出來。這條設定從預覽到轉檔都沿用,避免兩邊呈現不一致。

圖下面那行免責聲明

轉出來的圖不一定漂亮。Mermaid 的自動排版碰到節點多、標籤長的流程,偶爾會把兩個框疊在一起,或是讓箭頭直接穿過文字。轉成 JPG 之後那個跑版就定格了,使用者在 Word 裡也拉不動。

所以每張嵌進 Word 的流程圖跟協作圖,正下方固定加一行:

⚠️ 此圖為程式自動轉檔,可能跑版;原始碼見附錄,亦可貼到 mermaid.live 檢視。

這行只加在 Word。對話裡的 mermaid 是顯示器即時渲染的,不會有這個問題,多這行只是噪音。這種只在單一載體成立的規則,我後來都寫在 Word 生成那一段,不寫進 PRD 模板本身,免得對話端也跟著長出一句沒必要的警語。

圖轉壞了怎麼辦

沙箱環境不穩,轉圖這種事本來就有機率失敗。可能是某個節點文字裡有奇怪字元、可能是沙箱當下記憶體不夠、可能是套件版本對不上。重點是:它一定有失敗的時候,那一刻你不能讓使用者拿到一份開天窗的文件。

我最早的版本就犯了這個錯。轉圖失敗時,那個位置留了一個空白佔位符,使用者下載開來,流程那頁是空的。他不知道是壞了還是我忘了寫,只覺得這工具不靠譜。那次回饋讓我加了一條死規矩:不准留空白

現在的 fallback 是這樣接的。圖轉失敗,就不硬塞圖了,正文改成嵌入那張流程圖的 Mermaid 原始碼區塊,外加一句白紙黑字的說明:

流程圖自動轉圖失敗,以下為原始碼,可貼到 mermaid.live 產圖;附錄亦保留同份原始碼。

這樣使用者手上至少有內容,知道發生了什麼事,也知道怎麼補救(複製貼到 mermaid.live 兩秒就有圖)。退化成純文字的版面不好看,但比留一頁空白有用。設計一個會失敗的功能時,失敗時的呈現要跟正常時一起想好。

這也對應前面整套設計的一貫做法:狀態不理想的時候照實顯示,不用完整的外觀蓋過去。待確認清單是這樣、工時的低信心度標記是這樣,轉圖 fallback 也是這樣。

弄不好的目錄QQ

Word 生成上線之後我自己下載來看,覺得少了目錄。十幾頁的文件,SA 要找畫面清單得自己捲半天。python-docx 插目錄不難,塞一個 TOC 網域代碼進去,章節都套好 Heading 樣式就行:

TOC \o "1-3" \h \z \u

實際產出來有兩個問題。Word 的網域不會自己算頁碼,使用者得先按 F9 更新才看得到頁數,不然目錄那幾行後面全是空的;而且目錄那頁後面常常多出一整頁空白。我試著在產出後附一句「頁碼請按 F9 更新」,撐了兩天,還是把整個目錄砍了。現在標題頁後面直接接需求完整度總覽,再進正文。

回頭看,那句「請按 F9」本身就是警訊。一個功能要靠一句操作說明才成立,對使用者來說它就是沒做完。

規則寫太多

最後這件事,我覺得比前面所有技術細節都值得寫。

有天我下載一份剛產出的 Word,是一個線上請假需求的草稿,翻到流程那頁,又是那段 flowchart TD 語法。整份文件從頭到尾沒有一張圖。我把 .docx 解壓開來確認,裡面根本沒有 media 資料夾,代表它連轉圖那一步都沒跑,直接把語法貼進去交差。

第一反應是規則講得不夠重。我把那段改成硬的:每張圖「必須」先轉成圖片、正文「一律」放圖、「絕不」放原始碼,只有轉圖真的失敗才准放語法,還得標上警告。

隔天再看那份規則,我開始覺得不對勁,這條好像早就寫過了。翻 CHANGELOG 一查,「Word 一律轉圖」很早就定了,中間還對齊過一次,我前一天做的「強化」是同一條規則第三次重講。

真正的問題不在措辭。同一份需求,前一版產出的圖是好的,後一版就沒轉,這是模型執行上的浮動,寫幾個「必須」壓不住。而且整段塞滿「絕不」「唯一例外」讀起來像在跟它吵架,實測下來它在其他地方反而變得綁手綁腳。

所以我把硬措辭退回原本那版:Word 要轉圖嵌正文,轉不出來就走 fallback。偶爾漏轉,有 fallback 接著,這個程度可以接受。同時把散在三個檔案裡的同一條規則收回一處,其他地方只留一個指標。那次之後我給自己加了一條檢查:要加新規則之前,先確認這件事是不是已經寫在別的地方了。Day 7 講 Instructions 瘦身時提過同一件事,只是那時候我還沒把它變成固定動作。

最後所有東西都收進同一份 .docx:流程圖、畫面清單、Feature 規格、待確認清單、工時初估、Mermaid 原始語法、修改歷程,一份打包帶走,不分散成好幾個檔。SA 收到的是一份就好。

寫到這裡,鼠勾以從開場第一句問候、到吐出最後一份 Word,整條路都走完了。

明天是最後一篇,回頭聊聊那些沒寫進正文的東西:Prompt 怎麼防被亂玩、Backlog 的八種觸發怎麼治理這個一直在長的專案。還有一個到現在都還沒解掉的坑:它對「從零釐清新需求」很拿手,可是碰到「改既有功能、手上只有一份口傳沒文件的舊規格」就會水土不服。


這是 iThome 鐵人賽系列文章。明天見。
1788791879778


上一篇
【Day 28】工時估算框架
下一篇
【Day 30】收尾與下一步
系列文
利用Custom GPT+遊戲感來寫PRD30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言